import * as path from "node:path"
import * as fs from "node:fs"
import { Anime, AnimeInfo, GraphicInfo, Map, parseAllAnime, parseAllAnimeInfo, parseAllGraphicInfo, parseMap, parsePalet, saveAllGraphic } from "./crack-cg.js";
import { setFromArray, strcmp, strhash } from "@coldcloude/kai2";
import { packAllSprites, packMap } from "./repack-cg.js";

const G_PREFIX = "Graphic";
const GI_PREFIX = "GraphicInfo";
const A_PREFIX = "Anime";
const AI_PREFIX = "AnimeInfo";
const SPRITE_PREFIX = "Sprite";

const BIN_SUFFIX = ".bin";
const JSON_SUFFIX = ".json";

const configFile = "D:\\work\\gamedev\\resources\\CrossGate\\crackconfig.json";

const config = JSON.parse(fs.readFileSync(configFile,"utf8"));

const inputDir = config["inputDir"];
const outputDir = config["outputDir"];

const stepSet = setFromArray(config["steps"] as string[],strcmp,strhash);

//load graphic info

const graphicSuffix = config["graphicSuffix"];
const graphicInfoInputFile = path.join(inputDir,GI_PREFIX+graphicSuffix+BIN_SUFFIX);
const graphicInfoOutputFile = path.join(outputDir,GI_PREFIX+graphicSuffix+JSON_SUFFIX);

let graphicInfos:GraphicInfo[] = [];
if(stepSet.contains("gi")){
    console.log("parse graphic info");
    graphicInfos = parseAllGraphicInfo(graphicInfoInputFile);
    fs.writeFileSync(graphicInfoOutputFile,JSON.stringify(graphicInfos),"utf8");
}
else if(stepSet.contains("g")||stepSet.contains("pack")||stepSet.contains("mi")){
    console.log("load graphic info");
    const json = fs.readFileSync(graphicInfoOutputFile,"utf8");
    graphicInfos = JSON.parse(json);
}

//load and save graphic

const graphicInputFile = path.join(inputDir,G_PREFIX+graphicSuffix+BIN_SUFFIX);
const graphicOutputDir = path.join(outputDir,G_PREFIX+graphicSuffix);

if(stepSet.contains("g")){
    console.log("parse graphic");
    const paletFile = config["paletFile"];
    const palet = parsePalet(path.join(inputDir,paletFile));
    const graphicStart = config["graphicStart"];
    const graphicEnd = config["graphicEnd"];
    saveAllGraphic(palet,graphicInfos,graphicInputFile,graphicOutputDir,graphicStart,graphicEnd);
}

//load anime info

const animeSuffix = config["animeSuffix"];
const animeInfoInputFile = path.join(inputDir,AI_PREFIX+animeSuffix+BIN_SUFFIX);
const animeInfoOutputFile = path.join(outputDir,AI_PREFIX+animeSuffix+JSON_SUFFIX);

let animeInfos:AnimeInfo[] = [];
if(stepSet.contains("ai")){
    console.log("parse anime info");
    animeInfos = parseAllAnimeInfo(animeInfoInputFile);
    fs.writeFileSync(animeInfoOutputFile,JSON.stringify(animeInfos),"utf8");
}
else if(stepSet.contains("a")){
    console.log("load anime info");
    const json = fs.readFileSync(animeInfoOutputFile,"utf8");
    animeInfos = JSON.parse(json);
}

//load and save anime

const animeInputFile = path.join(inputDir,A_PREFIX+animeSuffix+BIN_SUFFIX);
const animeOutputFile = path.join(outputDir,A_PREFIX+animeSuffix+JSON_SUFFIX);

let animes:Anime[] = [];
if(stepSet.contains("a")){
    console.log("parse anime");
    const animeStart = config["animeStart"];
    const animeEnd = config["animeEnd"];
    animes = parseAllAnime(animeInfos,animeInputFile,animeStart,animeEnd);
    fs.writeFileSync(animeOutputFile,JSON.stringify(animes),"utf8");
}
else if(stepSet.contains("pack")){
    console.log("load anime");
    animes = JSON.parse(fs.readFileSync(animeOutputFile,"utf8"));
}

//save sprite
const spriteOutputDir = path.join(outputDir,SPRITE_PREFIX+animeSuffix);
if(stepSet.contains("pack")){
    const spriteStart = config["spriteStart"];
    const spriteEnd = config["spriteEnd"];
    const outputInfo = config["spriteOutputInfo"];
    const outputAtlas = config["spriteOutputAtlas"];
    packAllSprites(graphicInfos,animes,graphicOutputDir,spriteOutputDir,spriteStart,spriteEnd,outputInfo,outputAtlas);
}

//load map

const maps:Map[] = [];
const mapOutputDir = path.join(outputDir,"Map");
const mapIds:string[] = config["mapIds"];
if(stepSet.contains("mi")){
    for(const mapId of mapIds){
        const map = parseMap(graphicInfos,mapId,path.join(inputDir,"..","map","0",mapId+".dat"))
        maps.push(map);
        fs.writeFileSync(path.join(mapOutputDir,mapId+JSON_SUFFIX),JSON.stringify(map),"utf8");
    }
}
else if(stepSet.contains("mpack")){
    for(const mapId of mapIds){
        const map = fs.readFileSync(path.join(mapOutputDir,mapId+JSON_SUFFIX),"utf8");
        maps.push(JSON.parse(map));
    }
}

//pack map
if(stepSet.contains("mpack")){
    const outputInfo = config["mapOutputInfo"];
    const outputAtlas = config["mapOutputAtlas"];
    const outputTileMap = config["mapOutputTileMap"];
    for(const map of maps){
        packMap(map,graphicOutputDir,mapOutputDir,outputInfo,outputAtlas,outputTileMap);
    }
}
